import type { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
import { destroyTip, showTip as antdShowTip, sliceStr } from '@/lib/util';
import { next_reqBaseURL } from '../config/baseURL';
import { ResCode, ResponseData } from "@/app/api/util/res/code";
import localStore from '../util/LocalStorage';
import MyRequest, { addPendingRequest, getRequestKey, handlePostData, removePendingRequest, removeRepetitiveRequest } from '@/lib/util/axios';
/**前端专属的类 */
class FrontRequest extends MyRequest {
    /**前端部分 - 请求blob数据并下载 - get方式
    * @param url url。注意，此处需要自己写根路径
    * @param data post参数
    * @param name 导出的文件名，需要包含后缀  
    * @template T 请求参数类型
    */
    public downloadFile<T extends Record<string, any>>(url: string, data: T, name: string): Promise<void> {
        return new Promise(async (resolve, reject) => {
            try {
                antdShowTip("正在下载，请稍后", 'loading')
                const res = await request.get<Blob, T>(url, data, {
                    responseType: "blob",
                    baseURL: ""
                })
                const blob = new Blob([res]);
                const fileName = name;
                const elink = document.createElement('a');
                elink.download = fileName;
                elink.style.display = 'none';
                elink.href = URL.createObjectURL(blob);
                document.body.appendChild(elink);
                elink.click();
                URL.revokeObjectURL(elink.href); // 释放URL 对象
                document.body.removeChild(elink);
                antdShowTip("下载成功！")
                resolve()
            } catch (error: any) {
                antdShowTip("下载失败，请联系管理员排查", "error")
                reject(error?.message || error)
            }
        })
    }
}
/**默认的Request实例，给前端使用, 用来请求自己的Nextjs后端。 注：根路径为 /api， 只能在use client下使用(因为有弹窗) */
const request = new FrontRequest({ baseURL: next_reqBaseURL, timeout: 100 * 1000 }, (config) => {
    if (!config.noCancel) removeRepetitiveRequest(config);// 检查是否存在重复请求，若存在则取消已发的请求 
    addPendingRequest(config);// 把当前请求信息添加到pendingRequest对象中

    const { showTip = true, tipText = '加载中' } = config
    if (showTip) antdShowTip(tipText, 'loading', 0, getRequestKey(config)); //添加弹窗

    //请求拦截器，添加token
    // const token = localStore.getItem("token");
    // if (token) {
    //     config.headers!.Authorization = token;
    // }

}, [
    (res: AxiosResponse<ResponseData>) => {
        destroyTip(getRequestKey(res.config)); //移除弹窗
        removePendingRequest(res.config);//请求成功了就移除请求    
        if (res.data.code === 200) {
            // if (res.headers.token) {
            //     console.log('前端刷新token', res.headers.token);
            //     localStore.setItem('token', res.headers.token)
            // }
            return res.data.data; //直接返回装着数据的data
        } else {
            if (res.data instanceof Blob) return res.data; //如果返回的是blob，就放行 
            let message = res.data.message;
            switch (res.data.code) {
                case ResCode.BAD_REQUEST: //参数错误
                case ResCode.FAIL_REQUEST: //请求失败 - 当前不可用
                    break;
                // case ResCode.UNAUTHORIZED: //无整个权限
                //     setTimeout(() => {
                //         localStore.removeItem('token')
                //         window.location.assign('/');
                //     }, 1000);
                //     break;
                case ResCode.FORBIDDEN: //无模块权限   
                    setTimeout(() => {
                        window.location.assign('/');
                    }, 1000);
                    break;
                case ResCode.SERVER_ERROR: //系统错误
                    message = '系统错误，请联系管理员排查问题';
                    // router.push('/registration') 
                    break;
                default:
                    message = '未知错误，请检查网络或联系管理员';
                    console.log('未知请求错误 ', res.data);
                    break;
            }
            antdShowTip(`${message}`, "error", 3);
            return Promise.reject(message); //返回提示信息，可能可以在catch中用到
        }
    },
    (err: AxiosError) => {
        console.log(err);
        const config = err.config || {} as InternalAxiosRequestConfig<any>;

        destroyTip(getRequestKey(config)); //移除弹窗  
        removePendingRequest(config);// 从pendingRequest对象中移除请求   

        //如果是被取消的请求
        if (err.code === 'ERR_CANCELED') {
            console.log("被取消的重复请求：" + err.message);
            return Promise.reject('请求重复，取消')
        }

        // 这里用来处理http常见错误，进行全局提示
        let message = err.message;
        // 这里错误消息可以使用全局弹框展示出来  
        antdShowTip(`${message}，请检查网络或联系管理员！`, "error");
        // 这里是AxiosError类型，所以一般我们只reject我们需要的响应即可 
        return Promise.reject(err); //.response
    },
]);
export default request;
/**下载文件 */
export const downloadFile = request.downloadFile 